Golang JSON 序列化时动态忽略字段
在使用 JSON 时经常遇到需要忽略字段的情况,例如返回用户信息时不能返回密码,通常将注解 TAG 设为 json:"-" 即可:
1type User struct {
2 Account string `json:"account"`
3 Password string `json:"-"`
4 Nickname string `json:"nickname"`
5}但这样的静态配置会使字段在任何情况下都被忽略,有时希望可以根据需求动态的决定是否忽略某些字段。
可以通过反射将读取对象的字段名和字段值,过滤忽略的字段后存入一个 map[string]any 中,然后进行序列化:
1package utils
2
3import (
4 "encoding/json"
5 "reflect"
6)
7
8func JsonMarshalWithFilter(data any, ignore []string) ([]byte, error) {
9 filter := make(map[string]bool)
10 for i := range ignore {
11 name := ignore[i]
12 filter[name] = true
13 }
14 m := make(map[string]any)
15 metaType := reflect.TypeOf(data)
16 metaValue := reflect.ValueOf(data)
17 n := metaType.NumField()
18 for i := 0; i < n; i++ {
19 field := metaType.Field(i)
20 name := field.Tag.Get("json")
21 if filter[name] {
22 continue
23 }
24 value := metaValue.Field(i).Interface()
25 m[name] = value
26 }
27
28 return json.Marshal(m)
29}调用:
1package main
2
3import "utils"
4
5type User struct {
6 Account string `json:"account"`
7 Password string `json:"password"`
8 Nickname string `json:"nickname"`
9}
10
11func main() {
12 user := schema.User{
13 Account: "hubenchang0515",
14 Password: "xxxxxxxxx",
15 Nickname: "planc0515",
16 }
17
18 data, _ := utils.JsonMarshalWithFilter(user, []string{"password"})
19 println(string(data))
20}1$ go run .
2{"account":"hubenchang0515","nickname":"planc0515"}